package com.yxb.config.interceptor;

import com.yxb.constant.GlobalParam;
import com.yxb.util.ReturnToClientUtil;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.Instant;
import java.util.Map;

/**
 * @author
 */

public class ApiInterceptor extends HandlerInterceptorAdapter {

    private static final Logger LOGGER = LoggerFactory.getLogger(ApiInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        String sign = request.getParameter("sign");
        String signTime = request.getParameter("sign_time");
        String uri = request.getRequestURI();

        //验证参数
        if (StringUtils.isBlank(sign) || StringUtils.isBlank(signTime)) {
            LOGGER.info("uri:[{}] Auth check parameters invalid [{}|{}|{}]", uri, sign, signTime);
            ReturnToClientUtil.responseFailParameter("签名参数为空", request, response);
            return false;
        }

        // 校验签名时间
        Instant signTimeInstant = getSignTime(signTime);
        if (signTimeInstant == null) {
            LOGGER.info("uri:[{}] Auth check parameters sign time invalid [{}|{}]",uri,  sign, signTime);
            ReturnToClientUtil.responseFailParameter("校验签名时间失败", request, response);
            return false;
        }
        Instant twoMinutesAgo = Instant.now().minusSeconds(120);
        Instant thirtySecondsAfter = Instant.now().plusSeconds(30);
        if (signTimeInstant.isBefore(twoMinutesAgo) || signTimeInstant.isAfter(thirtySecondsAfter)) {
            LOGGER.info("uri:[{}] Auth check parameters sign time timeout [{}|{}]", uri, sign, signTimeInstant.toString());
            ReturnToClientUtil.responseFailParameter("请求已经过期了", request, response);
            return false;
        }

        String resign = resign(request);
        if (!StringUtils.equals(sign, resign)) {
            LOGGER.info("Auth check sign invalid param-sign:[{}], param-signTime:[{}], created-sign:[{}]", sign, signTime, resign);
            ReturnToClientUtil.responseFailParameter("签名错误", request, response);
            return false;
        }
        return super.preHandle(request, response, handler);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        super.afterCompletion(request, response, handler, ex);
    }

    @Override
    public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        super.afterConcurrentHandlingStarted(request, response, handler);
    }

    private Instant getSignTime(String signTime) {
        Instant instant = null;
        try {
            Long signTimeLong = Long.parseUnsignedLong(signTime);
            if (signTime.length() == 10) {
                instant = Instant.ofEpochSecond(signTimeLong);
            } else if (signTime.length() == 13) {
                instant = Instant.ofEpochMilli(signTimeLong);
            }
        } catch (NumberFormatException e) {
        }
        return instant;
    }

    /**
     * 加密
     */
    private String resign(HttpServletRequest request) {
        StringBuffer sb = new StringBuffer();
        sb.append("access_token").append(GlobalParam.TOKEN_SELF);
        request.getParameterMap().entrySet().stream()
                .sorted(Map.Entry.comparingByKey())
                .forEach(e -> {
                    String k = e.getKey();
                    String v = StringUtils.defaultString(e.getValue()[0]);
                    if (StringUtils.equals("sign", k)) {
                        return;
                    }
                    LOGGER.info("Auth check parameter [{}] [{}]", k, v);
                    sb.append(k).append(v);
                });

        LOGGER.info("具体的参数：[{}]", sb.toString());
        LOGGER.debug("Auth check sign string [{}]", sb.toString());

        String resign = DigestUtils.md5Hex(sb.toString());
        return resign;
    }

    public static void main(String[] args) {
        long time = System.currentTimeMillis();
        StringBuffer sb = new StringBuffer();
        sb.append("access_token").append(GlobalParam.TOKEN_SELF);
        sb.append("deviceIds").append("1836974485");
        sb.append("pageNo").append(1);
        sb.append("sign_time").append(1523694365353L);
        sb.append("size").append(20);
        sb.append("status").append(0);
        LOGGER.info(sb.toString());


        //String str= "access_tokena32a9f05-ec17-4013-8183-a7d283efae5f&deviceIds1836974485&pageNo1&sign_time1523694365353&size20&status0";
        String resign = DigestUtils.md5Hex(sb.toString());
        System.out.println(resign);
    }

}
